package it.antonio.ilpizze.servlet;

import it.antonio.ilpizze.servlet.core.Action;
import it.antonio.ilpizze.servlet.core.Converter;
import it.antonio.ilpizze.servlet.core.Parameters;
import it.antonio.ilpizze.servlet.core.Reflection;
import it.antonio.ilpizze.servlet.core.Responder;
import it.antonio.ilpizze.servlet.core.Results;
import it.antonio.ilpizze.servlet.core.Router;
import it.antonio.ilpizze.servlet.core.Reflection.ReflectionException;
import it.antonio.ilpizze.servlet.render.Json;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IlPizzeFilter implements Filter {

	private Converter converter = new Converter();
	private Responder responder = new Responder();
	private Parameters parameters = new Parameters(converter);
	private Router router = new Router();
	
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		router.loadForFilter(getClass());
	}

	@Override
	public void doFilter(ServletRequest sReq, ServletResponse sResp, FilterChain chain) throws IOException, ServletException {
		try{
			HttpServletRequest req = (HttpServletRequest) sReq;
			HttpServletResponse resp = (HttpServletResponse) sResp;
			
			Action action = router.resolve(req);
			
			if(action == null){
				resp.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			
			
			Object[] actionParams = parameters.resolve(req, resp, chain, action);
			Object result = Reflection.invoke(this, action.method, actionParams );
			
			responder.render(req, resp, null, result);
			
		} catch (ReflectionException e) {
			throw new ServletException(e.getCause());
		}
	}

	
	@Override
	public void destroy() {
		
	}
	
	protected Results.Text text(Object value){
		return new Results.Text(value.toString());
	}
	protected Results.Html html(Object html){
		return new Results.Html(html.toString());
	}
	protected Results.Json json(Object json){
		return new Results.Json(json.toString());
	}
	protected Results.Xml xml(Object xml){
		return new Results.Xml(xml.toString());
	}
	protected Results.Forward forward(String value){
		return new Results.Forward(value);
	}
	protected Results.Redirect redirect(String value){
		return new Results.Redirect(value);
	}
	protected Results.ResponseError error(int code){
		return new Results.ResponseError(code);
	}
	protected Results.ProceedFilterChain proceed(){
		return new Results.ProceedFilterChain();
	}

	protected Json convertToJson(Object value){
		return Json.convert(value);
	}
}
